package com.jifujun.junbatis.base;


import com.jifujun.junbatis.base.model.RootObject;
import com.jifujun.junbatis.base.util.SqlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.jdbc.SQL;

import java.util.Map;
import java.util.Objects;

/**
 * Create with IntelliJ IDEA
 * Project Name: junbatis
 * Package Name: club.emergency.junbatis.sql_base
 * Date: 2018/3/29 08:14
 * User: 快乐的小菌菌
 * Description:
 */
@Slf4j
public class SqlBuilder<ID, T extends RootObject> {

    public String insertOne(T t) {
        String insertOne = new SQL() {{
            INSERT_INTO(SqlUtil.getTableName(t.getClass(), false));
            INTO_COLUMNS(SqlUtil.sqlColumnBuilder(t.getClass(), false, false));
            INTO_VALUES(SqlUtil.sqlConditionColumnBuilder(t.getClass(), false));
        }}.toString();
        log.info(insertOne);
        return insertOne;
    }

    public String insertMore(String[] args, Map<String, Object> map, Class<T> clazz) {
        String insertList = new SQL() {{
            INSERT_INTO(SqlUtil.getTableName(clazz, false));
            INTO_COLUMNS(SqlUtil.sqlColumnBuilder(clazz, false, false));
            INTO_VALUES(args);
        }}.toString();
        log.info(insertList);
        log.info(map.toString());
        return insertList;
    }

    public String selectOnTable(String[] andArgs, Map<String, Object> andConditionContainer, String[] orArgs, Map<String, Object> orConditionContainer, Integer pageOffset, Integer pageSize, String[] orderByArgs, Boolean inPage, Class<T> clazz) {
        String selectOnTable = new SQL() {{
            SELECT_DISTINCT(SqlUtil.sqlAliasColumnBuilder(clazz, false));
            FROM(SqlUtil.getTableName(clazz, true));
            if (Objects.nonNull(andArgs) && andArgs.length != 0) {
                WHERE(andArgs);
                WHERE("obj1.using_type = 1");
            }
            if (Objects.nonNull(orArgs) && orArgs.length != 0) {
                OR();
                WHERE(orArgs);
                WHERE("obj1.using_type = 1");
            }
            if (Objects.nonNull(orderByArgs))
                ORDER_BY(orderByArgs);
        }}.toString();
        if (inPage)
            selectOnTable = selectOnTable + " limit " + pageOffset + "," + pageSize;
        log.info(selectOnTable);
        if (Objects.nonNull(andConditionContainer))
            log.info(andConditionContainer.toString());
        if (Objects.nonNull(orConditionContainer))
            log.info(orConditionContainer.toString());
        return selectOnTable;
    }

    public String selectMoreTable(Class<T> clazz) {
        String selectMoreTable = new SQL() {{
            SELECT_DISTINCT(
                    "obj1.user_name as userName," +
                            "obj1.user_age as UserAge," +
                            "obj1.student_id as studentId," +
                            "obj2.student_name as studentName," +
                            "obj2.student_age as studentAge," +
                            "obj2.student_sex as studentSex," +
                            "obj2.student_date as studentDate");
            FROM("user as obj1");
            LEFT_OUTER_JOIN("student as obj2 on obj1.student_id = obj2.id");
        }}.toString();
        log.info(selectMoreTable);
        return selectMoreTable;
    }

    public String deleteById(ID id, Class<T> clazz) {
        String deleteById = new SQL() {{
            DELETE_FROM(SqlUtil.getTableName(clazz, false));
            WHERE("id = #{arg0}");
        }}.toString();
        log.info(deleteById);
        return deleteById;
    }

    public String deleteByCondition(String[] args, Map<String, Object> deleteConditionContainer, Class<T> clazz) {
        String deleteByCondition = new SQL() {{
            DELETE_FROM(SqlUtil.getTableName(clazz, false));
            WHERE(args);
        }}.toString();
        log.info(deleteByCondition);
        return deleteByCondition;
    }

    public String updateByCondition(String[] args1, Map<String, Object> updateConditionContainer, Map<String, Object> getUpdateConditionObjectMap, String[] args2, Class<T> clazz) {
        String updateByCondition = new SQL() {{
            UPDATE(SqlUtil.getTableName(clazz, false));
            SET(args2);
            WHERE(args1);
        }}.toString();
        log.info(updateByCondition);
        log.info(updateConditionContainer.toString());
        log.info(getUpdateConditionObjectMap.toString());
        return updateByCondition;
    }

    public String count(String[] andArgs, Map<String, Object> andConditionContainer, String[] orArgs, Map<String, Object> orConditionContainer, Class<T> clazz) {
        String count = new SQL() {{
            SELECT_DISTINCT("count(*)");
            FROM(SqlUtil.getTableName(clazz, true));
            if (Objects.nonNull(andArgs) && andArgs.length != 0)
                WHERE(andArgs);
            if (Objects.nonNull(orArgs) && orArgs.length != 0) {
                OR();
                WHERE(orArgs);
            }
        }}.toString();
        log.info(count);
        if (Objects.nonNull(andConditionContainer))
            log.info(andConditionContainer.toString());
        if (Objects.nonNull(orConditionContainer))
            log.info(orConditionContainer.toString());
        return count;
    }

    public String getById(ID id, Class<T> clazz) {
        String getById = new SQL() {{
            SELECT_DISTINCT(SqlUtil.sqlAliasColumnBuilder(clazz, true));
            FROM(SqlUtil.getTableName(clazz, true));
            WHERE("id = #{arg0}");
        }}.toString();
        log.info(getById);
        return getById;
    }

    public String removeById(ID id, Class clazz) {
        String removeById = new SQL() {{
            UPDATE(SqlUtil.getTableName(clazz, false));
            SET("using_type = 0");
            WHERE("id = " + id);
        }}.toString();
        log.info(removeById);
        return removeById;
    }
}
